/*
 * Copyright 2009-2010 Belmont Software Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.belmont.backup;

import org.json.*;
import com.marimba.intf.util.IConfig;
import java.util.*;

/**
 * Class that contains all the configuration options for backup/restore operations.
 * XXX: I hate this class. Should be more like just a set of properties.
 */
public class Config implements IBackupConstants, IEventProducer {
    String backupRoot;
    boolean serviceEnabled = true;
    boolean allowBackupDirChange = true;
    String backupDirectories[];
    String includeFilters[];
    String excludeFilters[];
    String restoreDirectory;
    String compressedFileExtensions[];
    String backupSchedule;
    String configSchedule;
    String company;
    String product;
    String logoURL;
    String clientName;
    String companyURL;
    int maxVersions;
    int port = DEFAULT_PORT;

    public Config() {
    }

    public Config(JSONObject defaults) {
	initFrom(defaults);
    }

    public void addObserver(IEventObserver observer, int start, int end) {
	Producer.getInstance().addObserver(observer, start, end);
    }

    public void removeObserver(IEventObserver observer) {
	Producer.getInstance().removeObserver(observer);
    }

    public void initFrom(IConfig config) {
	String v = config.getProperty(CONFIG_PORT);

	if (v != null) {
	    try {
		port = Integer.parseInt(v.trim());
	    } catch (NumberFormatException ex) {
		ex.printStackTrace();
	    }
	}

	company = config.getProperty(CONFIG_BRANDING_COMPANY);
	product = config.getProperty(CONFIG_BRANDING_PRODUCT);
	logoURL = config.getProperty(CONFIG_BRANDING_LOGO_URL);
	clientName = config.getProperty(CONFIG_BRANDING_CLIENT_NAME);
	companyURL = config.getProperty(CONFIG_BRANDING_COMPANY_URL);
	backupSchedule = config.getProperty(CONFIG_BACKUP_SCHEDULE);
	configSchedule = config.getProperty(CONFIG_CONFIG_SCHEDULE);
	backupDirectories = arrayFromStringList(config.getProperty(CONFIG_DEFAULT_BACKUP_DIRECTORIES));
	includeFilters = arrayFromStringList(config.getProperty(CONFIG_DEFAULT_INCLUDE_FILTERS));
	excludeFilters = arrayFromStringList(config.getProperty(CONFIG_DEFAULT_EXCLUDE_FILTERS));
	backupRoot = config.getProperty(CONFIG_BACKUP_ROOT);
	if (config.getProperty(CONFIG_SERVICE_ENABLED) != null) {
	    serviceEnabled = "true".equals(config.getProperty(CONFIG_SERVICE_ENABLED));
	}
	v = config.getProperty(CONFIG_ALLOW_BACKUP_DIR_CHANGE);
	allowBackupDirChange = "true".equals(v);
	restoreDirectory = config.getProperty(CONFIG_DEFAULT_RESTORE_DIRECTORY);
	compressedFileExtensions = arrayFromStringList(config.getProperty(CONFIG_COMPRESSED_EXTENSIONS));
	Producer.getInstance().sendNotify(this, NOTIFY_CONFIG_CHANGED, this);
    }

    String[] arrayFromStringList(String v) {
	if (v == null) {
	    return null;
	}
	Vector<String> l = new Vector<String>();
	int idx;
	while ((idx = v.indexOf(';')) != -1) {
	    l.addElement(v.substring(0, idx));
	    v = v.substring(idx+1);
	}
	l.addElement(v);

	return (String[])l.toArray();
    }

    public void initFrom(JSONObject defaults) {
	backupDirectories = convertToJavaArray(defaults.optJSONArray(CONFIG_DEFAULT_BACKUP_DIRECTORIES));
	includeFilters = convertToJavaArray(defaults.optJSONArray(CONFIG_DEFAULT_INCLUDE_FILTERS));
	excludeFilters = convertToJavaArray(defaults.optJSONArray(CONFIG_DEFAULT_EXCLUDE_FILTERS));
	backupRoot = (String)defaults.opt(CONFIG_BACKUP_ROOT);
	if (defaults.opt(CONFIG_ALLOW_BACKUP_DIR_CHANGE) != null) {
	    allowBackupDirChange = defaults.optBoolean(CONFIG_ALLOW_BACKUP_DIR_CHANGE);
	}
	company = (String)defaults.opt(CONFIG_BRANDING_COMPANY);
	product = (String)defaults.opt(CONFIG_BRANDING_PRODUCT);
	logoURL = (String)defaults.opt(CONFIG_BRANDING_LOGO_URL);
	clientName = (String)defaults.opt(CONFIG_BRANDING_CLIENT_NAME);
	companyURL = (String)defaults.opt(CONFIG_BRANDING_COMPANY_URL);
	restoreDirectory = (String)defaults.opt(CONFIG_DEFAULT_RESTORE_DIRECTORY);
	compressedFileExtensions = convertToJavaArray(defaults.optJSONArray(CONFIG_COMPRESSED_EXTENSIONS));
	backupSchedule = (String)defaults.opt(CONFIG_BACKUP_SCHEDULE);
	configSchedule = (String)defaults.opt(CONFIG_CONFIG_SCHEDULE);
	if (defaults.opt(CONFIG_SERVICE_ENABLED) != null) {
	    serviceEnabled = "true".equals((String)defaults.opt(CONFIG_SERVICE_ENABLED));
	}
	String v = (String)defaults.opt(CONFIG_MAX_VERSIONS);
	if (v == null) {
	    maxVersions = 0;
	} else {
	    try {
		maxVersions = Integer.parseInt(v);
	    } catch (NumberFormatException ex) {
		ex.printStackTrace();
	    }
	}

	v = (String)defaults.opt(CONFIG_PORT);
	if (v == null) {
	    port = DEFAULT_PORT;
	} else {
	    try {
		port = Integer.parseInt(v);
	    } catch (NumberFormatException ex) {
		ex.printStackTrace();
	    }
	}
	Producer.getInstance().sendNotify(this, NOTIFY_CONFIG_CHANGED, this);
    }

    public int getPort() {
	return port;
    }

    public void setPort(int port) {
	this.port = port;
    }

    public boolean isServiceEnabled() {
	return serviceEnabled;
    }

    public void setServiceEnabled(boolean v) {
	this.serviceEnabled = v;
    }

    public void setBackupDirectories(String backupDirectories[]) {
	this.backupDirectories = backupDirectories;
    }

    public boolean getAllowBackupDirChange() {
	return allowBackupDirChange;
    }

    public void setAllowBackupDirChange(boolean value) {
	allowBackupDirChange = value;
    }

    public void setIncludeFilters(String includeFilters[]) {
	this.includeFilters = includeFilters;
    }

    public void setExcludeFilters(String excludeFilters[]) {
	this.excludeFilters = excludeFilters;
    }

    public void setBackupSchedule(String schedule) {
	this.backupSchedule = schedule;
    }

    public void setConfigSchedule(String schedule) {
	this.configSchedule = schedule;
    }

    public String getConfigSchedule() {
	return configSchedule;
    }

    public JSONObject getJSON() throws JSONException {
	JSONObject obj = new JSONObject();

	if (backupDirectories != null) {
	    for (int i=0; i < backupDirectories.length; i++) {
		obj.append(CONFIG_DEFAULT_BACKUP_DIRECTORIES, backupDirectories[i]);
	    }
	}

	if (includeFilters != null) {
	    for (int i=0; i < includeFilters.length; i++) {
		obj.append(CONFIG_DEFAULT_INCLUDE_FILTERS, includeFilters[i]);
	    }
	}

	if (excludeFilters != null) {
	    for (int i=0; i < excludeFilters.length; i++) {
		obj.append(CONFIG_DEFAULT_EXCLUDE_FILTERS, excludeFilters[i]);
	    }
	}
	obj.put(CONFIG_BACKUP_ROOT, backupRoot);
	obj.put(CONFIG_ALLOW_BACKUP_DIR_CHANGE, allowBackupDirChange);
	obj.put(CONFIG_DEFAULT_RESTORE_DIRECTORY, restoreDirectory);
	obj.put(CONFIG_MAX_VERSIONS, Integer.toString(maxVersions));
	obj.put(CONFIG_PORT, Integer.toString(port));
	obj.put(CONFIG_SERVICE_ENABLED, ((serviceEnabled) ? "true" : "false"));
	if (company != null) {
	    obj.put(CONFIG_BRANDING_COMPANY, company);
	}
	if (product != null) {
	    obj.put(CONFIG_BRANDING_PRODUCT, product);
	}
	if (logoURL != null) {
	    obj.put(CONFIG_BRANDING_LOGO_URL, logoURL);
	}
	if (clientName != null) {
	    obj.put(CONFIG_BRANDING_CLIENT_NAME, clientName);
	}
	if (companyURL != null) {
	    obj.put(CONFIG_BRANDING_COMPANY_URL, companyURL);
	}

	if (compressedFileExtensions != null) {
	    for (int i=0; i < compressedFileExtensions.length; i++) {
		obj.append(CONFIG_COMPRESSED_EXTENSIONS, compressedFileExtensions[i]);
	    }
	}
	if (backupSchedule != null) {
	    obj.put(CONFIG_BACKUP_SCHEDULE, backupSchedule);
	}
	if (configSchedule != null) {
	    obj.put(CONFIG_CONFIG_SCHEDULE, configSchedule);
	}

	return obj;
    }

    String[] convertToJavaArray(JSONArray a) {
	if (a == null) {
	    return null;
	}

	int l = a.length();
	String ar[] = new String[l];
	for (int i=0; i < l; i++) {
	    try {
		ar[i] = a.getString(i);
	    } catch (JSONException ex) {
		ex.printStackTrace();
		return null;
	    }
	}

	return ar;
    }

    public String getCompany() {
	return (company == null) ? "Belmont" : company;
    }

    public void setCompany(String c) {
	company = c;
    }

    public String getProduct() {
	return (product == null) ? "Backup Service" : product;
    }

    public void setProduct(String p) {
	product = p;
    }

    public String getClientName() {
	return (clientName == null) ? "Backup Service" : clientName;
    }

    public void setClientName(String c) {
	clientName = c;
    }

    public String getCompanyURL() {
	return (companyURL == null) ? "http://www.belmont-ss.com" : companyURL;
    }

    public void setCompanyURL(String u) {
	companyURL = u;
    }

    public String getLogoURL() {
	return (logoURL == null) ? "/ui/Belmont.png" : logoURL;
    }

    public void setLogoURL(String u) {
	logoURL = u;
    }

    public String toString() {
	try {
	    return getJSON().toString();
	} catch (Exception e) {
	    return super.toString();
	}
    }

    public int getMaxVersions() {
	return maxVersions;
    }

    public void setMaxVersions(int maxVersions) {
	this.maxVersions = maxVersions;
    }

    public String getBackupSchedule() {
	return backupSchedule;
    }

    public String getBackupRoot() {
	return backupRoot;
    }

    public void setBackupRoot(String root) {
	this.backupRoot = root;
    }

    public String[] getBackupDirectories() {
	return backupDirectories;
    }

    public String getRestoreDirectory() {
	return restoreDirectory;
    }

    public void setRestoreDirectory(String d) {
	restoreDirectory = d;
    }

    public String[] getDefaultIncludeFilter() {
	return includeFilters;
    }

    public String[] getDefaultExcludeFilter() {
	return excludeFilters;
    }

    public boolean getFilterOption() {
	return false;
    }

    public boolean getAllowAddBackupDirectory() {
	return allowBackupDirChange;
    }

    public boolean getAllowDeleteBackupDefaults() {
	return allowBackupDirChange;
    }

    public String getDefaultBackupSchedule() {
	return null;
    }
}